﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace AL.Doodled
{
    /// <summary>
    /// This is a widget component that handles the styling.
    /// </summary>
    public class Style
    {
        #region fields
        private string currentStateName;
        private Dictionary<string, dynamic> attributes;
        private Dictionary<string, StyleState> states;
        #endregion

        #region properties
        /// <summary>
        /// Get the name of the current StyleState.
        /// </summary>
        public string CurrentState
        { 
            get { return currentStateName; } 
        }

        public dynamic this[string key]
        {
            get { return attributes[key]; }
            set 
            {
                if (attributes.ContainsKey(key))
                    attributes[key] = value;
                else
                    attributes.Add(key, value);
            }
        }
        #endregion

        #region initialize
        public Style()
        {
            attributes = new Dictionary<string, dynamic>();
            states = new Dictionary<string, StyleState>();
            states.Add("default", new StyleState());
        }
        #endregion

        #region methods
        /// <summary>
        /// Returns the default state for the style, so it can be
        /// edited by the widget compiler.
        /// </summary>
        /// <returns>The default styleState.</returns>
        internal StyleState GetDefaultState()
        {
            return states["default"];
        }

        /// <summary>
        /// Adds a state to the styles state list.
        /// </summary>
        /// <param name="name">The name of the state.</param>
        /// <param name="state">The state.</param>
        internal void AddState(string name, StyleState state)
        {
            if(states.ContainsKey(name))
                throw new Exception("This state is allready defined.");
            else
                state.AddAttribute(name,state);
        }

        /// <summary>
        /// Alters the state, replacing it if it extists and adding
        /// it if there is no state with the entered name.
        /// </summary>
        /// <param name="name">The name of the state.</param>
        /// <param name="state">The state.</param>
        internal void AlterState(string name, StyleState state)
        {
            if (states.ContainsKey(name))
                states[name] = state;
            else
                states.Add(name, state);
        }

        /// <summary>
        /// Sets the current state of the style.
        /// </summary>
        /// <param name="name"></param>
        public void SetCurrentState(string name)
        {
            if (states.ContainsKey(name))
            {
                currentStateName = name;

                foreach (string key in states[name].AttributeKeys)
                {
                    if(attributes.ContainsKey(key))
                        attributes[key] = states[name][key];
                    else
                        attributes.Add(key, states[name][key]);
                }
            }
            else
                throw new KeyNotFoundException("There is no such state");
        }

        /// <summary>
        /// Evaluate if there is any attribute with the passed
        /// name.
        /// </summary>
        /// <param name="attributeName">The name of the attribute.</param>
        /// <returns>Does the attribute exist?</returns>
        public bool IsAttributeDefined(string attributeName)
        {
            return attributes.ContainsKey(attributeName);
        }
        #endregion
    }
}
